package phoenix.core.helpers.extensions;

import java.util.HashMap;

import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.testng.TestException;

import phoenix.core.PhoenixManager;
import phoenix.core.config.extensions.ConfigExt;
import phoenix.core.data_models.TestUserDataModel;
import core.ApplicationManager;
import core.helpers.DriverHelper;
import core.helpers.WebDriverHelper;

public class WebDriverHelperExt extends WebDriverHelper
{
	// PhoenixManager instance
	protected static PhoenixManager phoenix;

	public static HashMap<String, String> driverHandles;

	/**
	 * Initializes WebDriverHelperExt
	 * @param p_manager ApplicationManager instance
	 * @param p_phoenix PhoenixManager instance
	 */
	public WebDriverHelperExt(ApplicationManager p_manager, PhoenixManager p_phoenix)
	{
		super(p_manager);
		phoenix = p_phoenix;
	}

	public void clickElementByJS(By p_locator)
	{
		try
		{
			WebElement element = driver.findElement(p_locator);
			JavascriptExecutor executor = (JavascriptExecutor) driver;
			executor.executeScript("arguments[0].click();", element);
		}
		catch (Exception p_ex)
		{
			phoenix.log().errorAndScreen("clickElementByJS : Cannot click at " + p_locator.toString());
			throw new TestException("clickElementByJS : Cannot click at " + p_locator.toString());
		}
	}

	public void typeByIdJs(By p_elementID, String p_message)
	{
		try
		{
			String locator = (p_elementID.toString().contains("By.id")) ?
				p_elementID.toString().substring(7, p_elementID.toString().length()) :
				"Wrong locator";

			if (locator.equals("Wrong locator"))
			{
				throw new TestException("typeByIdJs does accept only locators by ID");
			}

			JavascriptExecutor executor = (JavascriptExecutor) driver;
			executor.executeScript("document.getElementById(\"" + locator + "\").innerHTML = \"" + p_message + "\";");
		}
		catch (Exception p_ex)
		{
			phoenix.log().errorAndScreen("typeByIdJs : Cannot type in " + p_elementID + " Error: " + p_ex.toString());
			throw new TestException("typeByIdJs : Cannot type in " + p_elementID + " Error: " + p_ex.toString());
		}
	}

	public void scrollWithOffset(WebElement p_webElement, int x, int y)
	{
		try
		{
			phoenix.log().info("Scroll to web element: " + p_webElement);
			JavascriptExecutor executor = (JavascriptExecutor) driver;
			executor.executeScript("arguments[0].scrollIntoView(true);", p_webElement);
			wait(1);
			executor.executeScript("window.scroll(" + (p_webElement.getLocation().x + x) + ","
				+ (p_webElement.getLocation().y + y) + ");");

		}
		catch (Exception p_ex)
		{
			phoenix.log().errorAndScreen("scrollWithOffset " + p_webElement + "\n" + p_ex);
			throw new TestException("scrollWithOffset " + p_webElement + "\n" + p_ex);
		}
	}

	/**
	 * @param p_script
	 * @deprecated
	 */
	@Deprecated
	public void jsExec(String p_script)
	{
		try
		{
			JavascriptExecutor executor = (JavascriptExecutor) driver;
			executor.executeScript(p_script);
		}
		catch (Exception p_ex)
		{
			phoenix.log().error(p_ex.toString());
		}
	}

	/**
	 * @param p_script
	 * @return
	 * @deprecated
	 */
	@Deprecated
	public String getTextByJs(String p_script)
	{
		try
		{
			JavascriptExecutor executor = (JavascriptExecutor) driver;
			return executor.executeScript(p_script).toString();
		}
		catch (Exception p_ex)
		{
			phoenix.log().errorAndScreen(p_ex.toString());
		}
		return null;
	}

	public HashMap<String, String> initSecondBrowser()
	{
		HashMap<String, String> l_map = new HashMap<String, String>();
		try
		{
			driverPrimary = driver;
			// Save instance of original driver
			String mainBrowserHandle = driver().getWindowHandle();
			l_map.put("main", mainBrowserHandle);
			this.setWindowSize(DriverHelper.driver, 0, 0, 1366, 768);

			DriverHelper.driverSecondary = manager.wd().runLocalBrowser(manager.testModel().getBrowserName(), manager.testModel().getProxy());

			Integer at = 0;
			while (DriverHelper.driverSecondary == null)
			{
				manager.log().info("We are waiting for another try");
				manager.wd().wait(120);

				if (at == 5)
				{
					manager.log().error("Unable to start browser after five attempts");
					throw new TestException("after 5 attempts");
				}
				at++;
				DriverHelper.driverSecondary = manager.wd().runLocalBrowser(manager.testModel().getBrowserName(), manager.testModel().getProxy());
			}

			// Init second window
			String browserSecondWindowHandle = DriverHelper.driverSecondary.getWindowHandle();
			this.setWindowSize(DriverHelper.driverSecondary, 0, 0, 1366, 768);
			l_map.put("second", browserSecondWindowHandle);

			this.switchDriverTo(DriverHelper.driverSecondary, browserSecondWindowHandle);
			this.openURL(manager.testModel().getSiteURL() + "/?ip_address=69.33.33.33");
			phoenix.setCountryCookie(manager.testModel().getLocation());
			this.switchDriverTo(this.driverPrimary, mainBrowserHandle);
		}
		catch (Exception p_ex)
		{
			phoenix.log().errorAndScreen(p_ex.toString());
		}

		return l_map;
	}

	public void getPrimaryWindow()
	{
		manager.log().info("Switch to primary window");
		this.switchDriverTo(DriverHelper.driverPrimary, this.driverHandles.get("main"));
	}

	public void getSecondWindow()
	{
		manager.log().info("Switch to secondary window");
		this.switchDriverTo(DriverHelper.driverSecondary, this.driverHandles.get("second"));
	}

	public void openAutologin(TestUserDataModel p_user)
	{
		try
		{
			String siteName = p_user.getSiteName();
			String userBuild = manager.testModel().getBuild();
			String userKey = p_user.getUserKey();

			if (siteName.isEmpty() || userBuild.isEmpty() || userKey.isEmpty())
			{
				throw new TestException("siteName => " + siteName + ", userBuild => " + userBuild + ", userKey => " + userKey);
			}

			if (manager.testModel().getBuild().contains(ConfigExt.BUILD_REL))
			{
				this.openURL("https://www." + siteName + "." + userBuild + ".platformphoenix.com/site/autologin/key/" + userKey);
			}
			else
			{
				this.openURL("https://www." + siteName + ".com/site/autologin/key/" + userKey);
			}
		}
		catch (Exception p_ex)
		{
			phoenix.log().errorAndScreen("openAutologin " + p_ex);
		}
	}

	public void openUserProfile(TestUserDataModel p_user)
	{
		try
		{
			this.openPage("/user/view/id/" + p_user.getId());
			this.waitForVisibility(phoenix.web().userPage().elements().blockScreenName, "Screen name");
		}
		catch (Exception p_ex)
		{
			phoenix.log().errorAndScreen("openUserProfile " + p_ex);
		}
	}

	public void openUserProfile(TestUserDataModel p_parentUser, TestUserDataModel p_targetUser)
	{
		try
		{
			// Open profile, make browse notice
			if (manager.testModel().getBuild().contains(ConfigExt.BUILD_REL))
			{
				this.openURL(
					"https://www." + p_parentUser.getSiteName() + "." + manager.testModel().getBuild() + ".platformphoenix.com/user/view/id/" + p_targetUser
						.getId());
			}
			else
			{
				this.openURL("https://www." + p_parentUser.getSiteName() + ".com/user/view/id/" + p_targetUser.getId());
			}
		}
		catch (Exception p_ex)
		{
			phoenix.log().errorAndScreen("openUserProfile " + p_ex);
		}
	}

	public void clickByJS(By p_element)
	{
		try
		{
			String p_locator = byToString(p_element);
			JavascriptExecutor executor = (JavascriptExecutor) driver;
			executor.executeScript("$('" + p_locator + "').click()");
			phoenix.log().info("click by JS at " + p_element.toString());
		}
		catch (Exception p_ex)
		{
			phoenix.log().errorAndScreen("clickByJS : Cannot click at: " + p_element);
			throw new TestException("clickByJS : Cannot click at: " + p_element);
		}
	}

	private String byToString(By p_element)
	{
		try
		{
			if (p_element.toString().contains("By.id"))
			{
				return p_element.toString().substring(7, p_element.toString().length());
			}

			else if (p_element.toString().contains("By.selector"))
			{
				return p_element.toString().substring(13, p_element.toString().length());
			}
			else
			{
				throw new TestException("Method do accept locator by ID or CSS");
			}
		}
		catch (Exception p_ex)
		{
			phoenix.log().error("Cannot convert By to String: " + p_ex);
		}
		return null;
	}

	public void selectItemInList(By p_path, By p_element, String p_value)
	{
		WebElement webElement = manager.wd().getWebElement(p_element);

		if (manager.testModel().getBrowserName().equals(manager.config().BROWSER_IEXPLORER))
		{
			scrollWithOffset(webElement, 0, -200);
		}

		webElement.click();
		String p_locator = byToString(p_path);
		JavascriptExecutor executor = (JavascriptExecutor) driver;
		executor.executeScript("$('" + p_locator + "(\"" + p_value + "\")').click()");
	}

	public void makeElementVisible(By p_element)
	{
		String p_locator = byToString(p_element);
		JavascriptExecutor executor = (JavascriptExecutor) driver;
		executor.executeScript("$('" + p_locator + "').show()");
	}

	public void makeElementHidden(By p_element)
	{
		String p_locator = byToString(p_element);
		JavascriptExecutor executor = (JavascriptExecutor) driver;
		executor.executeScript("$('" + p_locator + "').hide()");
	}

	public void click(WebElement el)
	{
		try
		{
			el.click();
		}
		catch (Exception p_ex)
		{
			throw new TestException("click by element : " + p_ex);
		}
	}

}